package com.ken.zeratul.i18n.source;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ken.zeratul.i18n.source.base.NacosResourceMessageSource;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * Nacos配置中心基于Json格式 管理I18n国际化配置文件的数据源
 * 这种管理方式采用单配置文件的方式管理国际化配置，所有语言的配置都放在一个配置文件中，只划分 通用国际化配置 和 特定微服务国际化配置
 *
 * 比如：
 * 通用汉语、英语、法语、日语....国际化配置 只对应配置文件 - dataId：message_base.json     groupName：base
 * 特定微服务汉语、英语、法语、日语....国际化配置 只对应配置文件 - dataId：message_微服务名称.json    groupName：微服务名称
 *
 * 配置文件的格式如下：
 *  {
 *      "zh_CN":{
 *          "key1":"你好",
 *          "key2":"世界"
 *      },
 *      "en": {
 *           "key1":"hello",
 *           "key2":"world"
 *      }
 *  }
 */
@Slf4j
public class JsonNacosResourceMessageSource extends NacosResourceMessageSource {

    /**
     * 默认的语言环境
     */
    private static final String DEFAULT_LANGUAGE = "default";



    /**
     * 返回所有的配置文件名称
     *
     * @param locale
     * @return
     */
    @Override
    protected List<String> getFileNames(Locale locale) {
        //获取基础Base名称
        Set<String> basenameSet = this.getBasenameSet();
        //BaseName直接
        return new ArrayList<>(basenameSet);
    }

    /**
     * 创建BaseHolder对象 - 由子类决定创建什么对象
     * @return
     */
    @Override
    protected BaseHolder createBaseHolder() {
        return new JsonHolder();
    }

    /**
     * Json格式国际化数据对象
     */
    @Data
    private static class JsonHolder extends BaseHolder<JSONObject> {

        /**
         * 转换方法，将配置信息，转换成相应的对象（具体对象由子类决定）
         * @param config
         * @return
         */
        @Override
        public JSONObject convertConfig(String config) {
            try {
                return JSON.parseObject(config);
            } catch (Exception e) {
                log.error("【国际化-基于Nacos配置】国际化配置Json解析失败：{}", config, e);
                return null;
            }
        }

        /**
         * 从Holder对象中，根据语言 和 code 获取国际化value
         *
         * @param jsonObject
         * @param key
         * @return
         */
        @Override
        public String getValue(JSONObject jsonObject, Locale locale, String key) {
            List<String> languages = this.getLanguages(locale);
            if (CollectionUtils.isEmpty(languages)) return null;

            for (String language : languages) {
                try {
                    String value = jsonObject.getJSONObject(language).getString(key);
                    if (StringUtils.hasLength(value)) return value;
                } catch (Exception e){
                    //如果解析出错，则继续下一个语言环境
                }
            }
            return null;
        }

        /**
         * 返回配置后缀
         *
         * @return
         */
        @Override
        protected String getSuffix() {
            return "json";
        }

        /**
         * 根据语言环境 获取 环境字符串集合 按优先级排列
         * 比如：zh_CN环境，解析结果为：
         * zh_CN
         * zh
         * default
         * 优先级从高到低
         * @param locale
         * @return
         */
        private List<String> getLanguages(Locale locale) {
            if (Objects.isNull(locale))
                return null;

            List<String> result = new ArrayList<>(3);
            String language = locale.getLanguage();
            String country = locale.getCountry();
            result.add(DEFAULT_LANGUAGE);//默认的语言环境

            StringBuilder temp = new StringBuilder();
            if (StringUtils.hasLength(language)) {
                temp.append(language);
                result.add(0, temp.toString());
            }

            temp.append('_');
            if (StringUtils.hasLength(country)) {
                temp.append(country);
                result.add(0, temp.toString());
            }
            return result;
        }
    }
}
